<?php

/**
 * This is the model class for table "password_reset".
 *
 * The followings are the available columns in table 'password_reset':
 * @property integer $id_reset
 * @property integer $ci
 * @property string $token
 * @property string $expires
 * @property boolean $used
 *
 * The followings are the available model relations:
 * @property Usuario $ci0
 *
 * Propiedades adicionales
 * @property string $email
 */
class PasswordReset extends CActiveRecord
{
	public $email;
	public $hashToken;
	
	/**
	 * Returns the static model of the specified AR class.
	 * @param string $className active record class name.
	 * @return PasswordReset the static model class
	 */
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return 'password_reset';
	}

	/**
	 * @return array validation rules for model attributes.
	 */
	public function rules()
	{
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
			//reglas para la accion create (en realidad insert)
			array(
				'ci, email',
				'required',
				'on'=>'insert',
				'message'=>'Por favor completa el campo {attribute}.',
			),
			array(
				'ci, email',
				'safe',
				'on'=>'insert',
			),
			
			//reglas para la accion reset
			array(
				'token',
				'required',
				'on'=>'reset',
				'message'=>'Por favor completa el campo {attribute}.',
			),
			array(
				'token',
				'checkToken',
				'on'=>'reset',
				'message'=>'El token no es válido',
			),

			//reglas genericas
			array('ci', 'numerical', 'integerOnly'=>true),
			array('token', 'length', 'max'=>250),
			
			// The following rule is used by search().
			// Please remove those attributes that should not be searched.
			array('id_reset, ci, token, expires, used', 'safe', 'on'=>'search'),
		);
	}

	/**
	 * @return array relational rules.
	 */
	public function relations()
	{
		// NOTE: you may need to adjust the relation name and the related
		// class name for the relations automatically generated below.
		return array(
			'ci0' => array(self::BELONGS_TO, 'Usuario', 'ci'),
		);
	}

	/**
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels()
	{
		return array(
			'id_reset' => 'Id Reset',
			'ci' => 'Cédula de Identidad',
			'token' => 'Token',
			'expires' => 'Expires',
			'used' => 'Used',
			'email' => 'Email',
		);
	}

	/**
	 * Retrieves a list of models based on the current search/filter conditions.
	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
	 */
	public function search()
	{
		// Warning: Please modify the following code to remove attributes that
		// should not be searched.

		$criteria=new CDbCriteria;

		$criteria->compare('id_reset',$this->id_reset);
		$criteria->compare('ci',$this->ci);
		$criteria->compare('token',$this->token,true);
		$criteria->compare('expires',$this->expires,true);
		$criteria->compare('used',$this->used);

		return new CActiveDataProvider($this, array(
			'criteria'=>$criteria,
		));
	}
	
	public function beforeSave()
	{
		parent::beforeSave();
		
		if($this->scenario == 'insert')
		{
			//consultar la bd y buscar la cédula y el email
			$count = Usuario::model()->count('ci='.$this->ci.' and email=\''.$this->email.'\'');
			Yii::log('Usuario count: '.$count,'info','PasswordReset');
			//si existe el usuario y el mail es correcto
			if($count == 1)
			{
				//verificar si ya hay una entrada en la tabla para la ci
				$count = $this->count('ci='.$this->ci.' and used=false');
				//ya existe
				if($count == 1)
				{
					//buscar y borrar el registro
					$reg = PasswordReset::model()->findByAttributes(array('ci'=>$this->ci, 'used'=>false));
					$reg->delete();
					Yii::log('Ya existe una entrada, borrando...','info','PasswordReset');
				}
				
				//generar un nuevo token
				$this->token = $this->generateToken($this->ci);
				$this->expires = $this->generateTimestamp();
				$this->used = false;
				Yii::log('Token: '.$this->token.' | Expires: '.$this->expires.' | Used: '.var_export($this->used),'info','PasswordReset');
				
			}
			else //si no existe mostrar un error
			{
				$this->addError('ci','Cédula de Identidad o Email inválido');
				return false;
			}
		}
		
		return true;
	}
	
	public function afterSave()
	{
		parent::afterSave();
		
		if($this->scenario == 'insert')
		{	
			$user = Usuario::model()->findByPk($this->ci);
			
			$to = $user->email;
			$token = urlencode(base64_encode(base_convert($this->ci,10,36).','.$this->token));
			$message = 'Password reset link <a href="'.Yii::app()->createUrl('passwordreset/reset',array('token'=>$token)).'">'.Yii::app()->createUrl('passwordreset/reset',array('token'=>$token)).'</a>';
			
			$mail=Yii::app()->Smtpmail;
			$subject = 'Recuperación de Contraseña';
			$result = $mail->sendMail($to,$subject,$message);
			Yii::log("Mail result: $result",'info','PasswordReset');
		}
	}
	
	/**
	* Genera un token
	*
	* @param string $salt La semilla sobre la cual generar el token
	* @return string El token generado
	*/
	public function generateToken($salt)
	{
		return base_convert(crc32(md5($salt.time())),10,36);	
	}
	
	/**
	* Genera un timestamp basado en la fecha y hora del servidor + un offset de 24 horas
	*
	* El offset es usado para permitir que el link sea válido por hasta un dia.
	*
	* @return string El timestamp generado en formato YYYY-MM-DD HH:MM:SS
	*/
	public function generateTimestamp()
	{
		return date('Y-m-d H:i:s', time()+84600);
	}
	
	public function retriveToken($token)
	{
		$token = urldecode(base64_decode($token));
		$token = explode(',',$token);
		if(sizeof($token) == 2)
		{
			$ci = base_convert($token[0],36,10);
			$tok = $token[1];
		
			return array(
						'ci'=>$ci,
						'token'=>$tok,
						);
		}
		else
		{
			return null;
		}
	}
	
	public function checkToken($attribute,$params){
		$this->hashToken = $this->token;
		$t = $this->retriveToken($this->hashToken);
		if($t !== null)
		{
			$token = $t['token'];
			$ci = $t['ci'];
			
			Yii::log("CI: $ci | Token: $token",'info','PasswordReset');
			
			$now = date('Y-m-d H:i:s', time());
			
			$count = PasswordReset::model()->count("ci=$ci and token='$token' and used=false and expires>=date('$now')");
			Yii::log('checkToken: '.$count,'info','PasswordReset');
			if($count == 1)
			{
				$m = PasswordReset::model()->findByAttributes(array('ci'=>$ci,'token'=>$token,'used'=>false));
				$m->saveAttributes(array('used'=>true));
				
				$this->ci = $m->ci;
				$this->token = $m->token;
				$this->expires = $m->expires;
				$this->used = $m->used;
			}
			else
			{
				Yii::log("Token inválido | ci=$ci | token=$token",'error','PasswordReset');
				$this->addError('token','Token inválido');
			}
		}
		else
		{
			Yii::log('Token inválido (null)','error','PasswordReset');
			$this->addError('token','Token inválido');
		}
	}

}